Sphinxのインデックス作成時にMeCabのユーザー辞書を利用する
こんにちは。サービスグループの武田です。
先日Sphinxの分かち書きアルゴリズムにMeCabを使用する方法をエントリしました。
その最後に クラスメソッド などの固有名詞がインデックスされなくなってしまったという課題が残っていました。今回はMeCabのユーザー辞書を利用することで改善できそうということで、その方法を紹介します。
環境
今回は次の環境で検証しました。なおSphinxの言語は日本語を指定しています(language = 'ja'
)。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.13.6 BuildVersion: 17G65 $ python3 -V Python 3.7.0 $ pip3 -V pip 18.0 from /usr/local/lib/python3.7/site-packages/pip (python 3.7) $ pip3 list | grep -e Sphinx -e mecab -e jsbeautifier jsbeautifier 1.8.6 mecab-python3 0.7 Sphinx 1.7.4
MeCabをそのまま使ったケース
まずは前回のエントリと同様にMeCabをそのまま使った場合に、どのようにインデックスが作られるのかを確認します。conf.py
は同じ内容です。
html_search_options = { 'type': 'sphinx.search.ja.MecabSplitter', 'dic_enc': 'utf-8', 'dict': '/usr/local/lib/mecab/dic/mecab-ipadic-neologd' }
次にSphinxをビルドし、作成されたインデックスの内容を確認します。ビルド対象のドキュメントは実際に運用しているもので、そこから一部抜粋してみます。
$ make clean && make html $ cat build/html/searchindex.js \ | python3 -c 'from sys import stdin; print(stdin.readline().encode().decode("unicode-escape"))' \ | js-beautify \ | grep -e クラス -e メソッド -e メンバーズ \ | grep -v titles "クラス": [2, 4], "クラスメソッドメンバーズ": [0, 4], "クラスメソッドメンバーズポータル": 4, "メソッド": [2, 4], "メンバーズ": [0, 1, 3], "メンバーズポータル": 3, "クラスメソッドメンバーズ": 1, "メンバーズ": [2, 4], "メンバーズポータル": 2,
確かに クラスメソッド がインデックスされていないですね(クラスとメソッドに分かれてしまっている)。
MeCabのユーザー辞書を利用するケース
まず大前提の整理です。MeCabには、システム辞書 と ユーザー辞書 の2種類の辞書があります。そのため自分で辞書に単語を追加したい場合、どちらかの辞書を使用することになります。今回の構成ではmecab-ipadic-NEologd
をシステム辞書として利用しているためそこに手を加えるか、ユーザー辞書を用意することになります。
ところで、Sphinxのhtml_search_options
にはシステム辞書を指定するオプションはありますが、ユーザー辞書を指定するオプションがありません。そうするとシステム辞書を使うしかないかなとも思ったのですが、結局はMeCabの話なのでそっちで解決できないかと調べました。
調べた結果、MeCabのコマンドラインオプションか、設定ファイルでユーザー辞書を指定できることがわかりました。起動オプションはSphinx経由では指定できませんでしたが、設定ファイルならなんとかなりそうです。次に設定ファイルの指定方法、優先順位を調べました。簡潔にまとめると次のようになります(UNIX環境の場合)。
- コマンドラインオプションの
-r
または--rcfile
で指定されたファイル ~/.mecabrc
ファイル(環境変数HOME
が設定されている場合)- 環境変数
MECABRC
で指定されたファイル /usr/local/etc/mecabrc
ファイルecho "$(mecab-config --sysconfdir)/mecabrc"
で確認できます
このうち1は採用できません(コマンドラインオプションが指定できないため)。2、3、4はどれでも採用できそうですが、ユーザー辞書および設定ファイルを一緒にリポジトリで管理できると便利そうですので、3を採用してみます。
方針が決まったのでユーザー辞書を用意していきます。まずはCSVファイルです。
クラスメソッド,-1,-1,1,名詞,固有名詞,組織,*,*,*,クラスメソッド,クラスメソッド,クラスメソッド
次にこのCSVファイルをコンパイルします。
$ cd /path/to $ /usr/local/Cellar/mecab/0.996/libexec/mecab/mecab-dict-index \ -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd \ -u classmethod.dic \ -f utf-8 \ -t utf-8 \ classmethod.userdic.csv reading classmethod.userdic.csv ... 1 emitting double-array: 100% |###########################################| done!
コンパイルできましたね。続いてmecabrc
ファイルを用意します。
dicdir = /usr/local/lib/mecab/dic/mecab-ipadic-neologd userdic = /path/to/classmethod.dic
最後に、conf.py
でシステム辞書を指定する必要がなくなったのでその設定は削除してしまいます。
html_search_options = { 'type': 'sphinx.search.ja.MecabSplitter' }
これで準備ができました。それでは作成したユーザー辞書を利用してインデックスを作成してみます。
$ export MECABRC=/path/to/mecabrc $ make clean && make html $ cat build/html/searchindex.js \ | python3 -c 'from sys import stdin; print(stdin.readline().encode().decode("unicode-escape"))' \ | js-beautify \ | grep -e クラス -e メソッド -e メンバーズ \ | grep -v titles "クラスメソッド": [0, 2, 4], "メンバーズ": [0, 3], "メンバーズポータル": [3, 4], "クラスメソッド": 1, "メンバーズ": [1, 2, 4], "メンバーズポータル": 2,
クラスメソッド がきちんとインデックスされています!
まとめ
SphinxからMeCabを利用する際の、ユーザー辞書の使い方を調べてみました。途中まではシステム辞書でどうにかしないといけないかなと半ば諦めかけていましたが、ユーザー辞書が簡単に使えそうでよかったです。